/* eslint-disable react-hooks/exhaustive-deps */
import React, {
  forwardRef,
  useImperativeHandle,
  useEffect,
  useState,
  useRef,
} from 'react';
import * as echarts from 'echarts';
import type { EChartsType } from 'echarts';
import { resize } from '@/utils';
import { isString, isFunction } from '@/utils/is';
import type { ChartProps } from './types';

export type ChartRef = {
  getChartInstance: () => EChartsType;
};
let loadingOpt = {
  text: '数据加载中...',
  color: '#1677ff',
  textColor: '#000',
  maskColor: 'rgba(255, 255, 255, 0.8)',
  zlevel: 0,
  // 字体大小。从 `v4.8.0` 开始支持。
  fontSize: 12,
  // 是否显示旋转动画（spinner）。从 `v4.8.0` 开始支持。
  showSpinner: true,
  // 旋转动画（spinner）的半径。从 `v4.8.0` 开始支持。
  spinnerRadius: 10,
  // 旋转动画（spinner）的线宽。从 `v4.8.0` 开始支持。
  lineWidth: 3,
  // 字体粗细。从 `v5.0.1` 开始支持。
  fontWeight: 'normal',
  // 字体风格。从 `v5.0.1` 开始支持。
  fontStyle: 'normal',
  // 字体系列。从 `v5.0.1` 开始支持。
  fontFamily: 'sans-serif',
};

const Chart: React.ForwardRefRenderFunction<ChartRef, ChartProps> = (
  { chartStyle, ...props },
  ref
) => {
  const {
    option,
    onEvents,
    notMerge = false,
    lazyUpdate = false,
    showLoading,
    loadingOption = { ...loadingOpt, ...props.loadingOption },
  } = props;
  const [chart, setChart] = useState<EChartsType>();
  const chartRef = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (chartRef.current && !chart) {
      let instance = echarts.init(chartRef.current, props.theme, props.opts);
      if (onEvents) {
        bindEvents(instance, onEvents);
      }
      setChart(instance);
    }
    return () => {
      chart?.dispose();
    };
  }, []);

  useEffect(() => {
    chart?.setOption(option, notMerge, lazyUpdate);
  }, [option]);

  useEffect(() => {
    if (showLoading) {
      chart?.showLoading(loadingOption);
    } else {
      chart?.hideLoading();
    }
  }, [showLoading]);

  useEffect(() => {
    if (chartRef.current) {
      resize(chart as EChartsType, chartRef.current);
    }
  }, [chart]);

  const bindEvents = (
    instance: EChartsType,
    events: ChartProps['onEvents']
  ) => {
    function _bindEvent(eventName: string, func: Function) {
      // ignore the event config which not satisfy
      if (isString(eventName) && isFunction(func)) {
        // binding event

        instance.on(eventName, param => {
          func(param, instance);
        });
      }
    }

    // bind
    for (const eventName in events) {
      if (Object.prototype.hasOwnProperty.call(events, eventName)) {
        _bindEvent(eventName, events[eventName]);
      }
    }
  };

  const getChartInstance = () => {
    return chart as EChartsType;
  };
  useImperativeHandle(ref, () => ({
    getChartInstance,
  }));
  return (
    <div ref={chartRef} className={props.className} style={chartStyle}></div>
  );
};

export default forwardRef(Chart);
